package com.marketing.tenant.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.marketing.tenant.entity.TenantUsage;
import com.marketing.tenant.mapper.TenantUsageMapper;
import com.marketing.tenant.service.TenantUsageService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 租户使用统计服务实现
 * 
 * @author Marketing System
 * @since 2024-09-25
 */
@Service
public class TenantUsageServiceImpl implements TenantUsageService {
    
    private static final Logger log = LoggerFactory.getLogger(TenantUsageServiceImpl.class);
    
    @Autowired
    private TenantUsageMapper tenantUsageMapper;
    
    @Override
    public TenantUsage getTenantUsage(Long tenantId, LocalDate statDate) {
        try {
            LambdaQueryWrapper<TenantUsage> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(TenantUsage::getTenantId, tenantId)
                   .eq(TenantUsage::getStatDate, statDate);
            
            TenantUsage usage = tenantUsageMapper.selectOne(wrapper);
            log.debug("获取租户使用统计成功，租户ID: {}, 日期: {}", tenantId, statDate);
            return usage;
        } catch (Exception e) {
            log.error("获取租户使用统计失败: {}", e.getMessage(), e);
            throw new RuntimeException("获取租户使用统计失败: " + e.getMessage());
        }
    }
    
    @Override
    public List<TenantUsage> getTenantUsageByDateRange(Long tenantId, LocalDate startDate, LocalDate endDate) {
        try {
            LambdaQueryWrapper<TenantUsage> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(TenantUsage::getTenantId, tenantId)
                   .ge(TenantUsage::getStatDate, startDate)
                   .le(TenantUsage::getStatDate, endDate)
                   .orderByAsc(TenantUsage::getStatDate);
            
            List<TenantUsage> usageList = tenantUsageMapper.selectList(wrapper);
            log.debug("获取租户日期范围使用统计成功，租户ID: {}, 开始日期: {}, 结束日期: {}", tenantId, startDate, endDate);
            return usageList;
        } catch (Exception e) {
            log.error("获取租户日期范围使用统计失败: {}", e.getMessage(), e);
            throw new RuntimeException("获取租户日期范围使用统计失败: " + e.getMessage());
        }
    }
    
    @Override
    public List<TenantUsage> getRecentTenantUsage(Long tenantId, Integer days) {
        try {
            List<TenantUsage> usageList = tenantUsageMapper.selectRecentByTenantId(tenantId, days);
            log.debug("获取租户最近使用统计成功，租户ID: {}, 天数: {}", tenantId, days);
            return usageList;
        } catch (Exception e) {
            log.error("获取租户最近使用统计失败: {}", e.getMessage(), e);
            throw new RuntimeException("获取租户最近使用统计失败: " + e.getMessage());
        }
    }
    
    @Override
    public Map<String, Object> getTenantUsageSummary(Long tenantId, Integer days) {
        try {
            Map<String, Object> summary = new HashMap<>();
            
            // 获取最近的使用统计
            List<TenantUsage> recentUsage = tenantUsageMapper.selectRecentByTenantId(tenantId, days);
            
            // 计算摘要信息
            long totalApiCalls = 0;
            long totalLogins = 0;
            long maxStorageUsed = 0;
            
            for (TenantUsage usage : recentUsage) {
                switch (usage.getMetricName()) {
                    case "api_calls":
                        totalApiCalls += usage.getMetricValue();
                        break;
                    case "login_count":
                        totalLogins += usage.getMetricValue();
                        break;
                    case "storage_used":
                        maxStorageUsed = Math.max(maxStorageUsed, usage.getMetricValue());
                        break;
                }
            }
            
            summary.put("totalApiCalls", totalApiCalls);
            summary.put("totalLogins", totalLogins);
            summary.put("maxStorageUsed", maxStorageUsed);
            summary.put("days", days);
            
            log.debug("获取租户使用统计摘要成功，租户ID: {}, 天数: {}", tenantId, days);
            return summary;
        } catch (Exception e) {
            log.error("获取租户使用统计摘要失败: {}", e.getMessage(), e);
            throw new RuntimeException("获取租户使用统计摘要失败: " + e.getMessage());
        }
    }
    
    @Override
    public boolean recordApiCall(Long tenantId, Long count) {
        try {
            LocalDate today = LocalDate.now();
            int result = tenantUsageMapper.incrementApiCalls(tenantId, today, count);
            log.info("记录API调用成功，租户ID: {}, 次数: {}", tenantId, count);
            return result > 0;
        } catch (Exception e) {
            log.error("记录API调用失败: {}", e.getMessage(), e);
            throw new RuntimeException("记录API调用失败: " + e.getMessage());
        }
    }
    
    @Override
    public boolean recordApiCall(Long tenantId) {
        return recordApiCall(tenantId, 1L);
    }
    
    @Override
    public boolean recordLogin(Long tenantId, Integer count) {
        try {
            LocalDate today = LocalDate.now();
            int result = tenantUsageMapper.incrementLoginCount(tenantId, today, count);
            log.info("记录用户登录成功，租户ID: {}, 次数: {}", tenantId, count);
            return result > 0;
        } catch (Exception e) {
            log.error("记录用户登录失败: {}", e.getMessage(), e);
            throw new RuntimeException("记录用户登录失败: " + e.getMessage());
        }
    }
    
    @Override
    public boolean recordLogin(Long tenantId) {
        return recordLogin(tenantId, 1);
    }
    
    @Override
    public boolean updateStorageUsage(Long tenantId, Long storageUsed) {
        try {
            LocalDate today = LocalDate.now();
            int result = tenantUsageMapper.updateStorageUsed(tenantId, today, storageUsed);
            log.info("更新存储使用量成功，租户ID: {}, 存储使用量: {} bytes", tenantId, storageUsed);
            return result > 0;
        } catch (Exception e) {
            log.error("更新存储使用量失败: {}", e.getMessage(), e);
            throw new RuntimeException("更新存储使用量失败: " + e.getMessage());
        }
    }
    
    @Override
    public boolean updateUserStats(Long tenantId, Integer userCount, Integer activeUserCount) {
        try {
            LocalDate today = LocalDate.now();
            int result = tenantUsageMapper.updateUserCount(tenantId, today, userCount, activeUserCount);
            log.info("更新用户统计信息成功，租户ID: {}, 用户总数: {}, 活跃用户数: {}", tenantId, userCount, activeUserCount);
            return result > 0;
        } catch (Exception e) {
            log.error("更新用户统计信息失败: {}", e.getMessage(), e);
            throw new RuntimeException("更新用户统计信息失败: " + e.getMessage());
        }
    }
    
    @Override
    public boolean initTodayUsage(Long tenantId) {
        try {
            LocalDate today = LocalDate.now();
            
            // 检查今天是否已有记录
            LambdaQueryWrapper<TenantUsage> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(TenantUsage::getTenantId, tenantId)
                   .eq(TenantUsage::getStatDate, today);
            
            long count = tenantUsageMapper.selectCount(wrapper);
            
            // 如果没有记录，则初始化
            if (count == 0) {
                // 初始化API调用次数
                TenantUsage apiUsage = new TenantUsage();
                apiUsage.setTenantId(tenantId);
                apiUsage.setStatDate(today);
                apiUsage.setMetricName("api_calls");
                apiUsage.setMetricValue(0L);
                apiUsage.setUnit("次");
                apiUsage.setDescription("API调用次数");
                tenantUsageMapper.insert(apiUsage);
                
                // 初始化登录次数
                TenantUsage loginUsage = new TenantUsage();
                loginUsage.setTenantId(tenantId);
                loginUsage.setStatDate(today);
                loginUsage.setMetricName("login_count");
                loginUsage.setMetricValue(0L);
                loginUsage.setUnit("次");
                loginUsage.setDescription("登录次数");
                tenantUsageMapper.insert(loginUsage);
                
                // 初始化存储使用量
                TenantUsage storageUsage = new TenantUsage();
                storageUsage.setTenantId(tenantId);
                storageUsage.setStatDate(today);
                storageUsage.setMetricName("storage_used");
                storageUsage.setMetricValue(0L);
                storageUsage.setUnit("bytes");
                storageUsage.setDescription("已用存储空间");
                tenantUsageMapper.insert(storageUsage);
                
                // 初始化用户数量
                TenantUsage userUsage = new TenantUsage();
                userUsage.setTenantId(tenantId);
                userUsage.setStatDate(today);
                userUsage.setMetricName("user_count");
                userUsage.setMetricValue(0L);
                userUsage.setUnit("个");
                userUsage.setDescription("用户总数");
                tenantUsageMapper.insert(userUsage);
                
                // 初始化活跃用户数
                TenantUsage activeUserUsage = new TenantUsage();
                activeUserUsage.setTenantId(tenantId);
                activeUserUsage.setStatDate(today);
                activeUserUsage.setMetricName("active_user_count");
                activeUserUsage.setMetricValue(0L);
                activeUserUsage.setUnit("个");
                activeUserUsage.setDescription("活跃用户数");
                tenantUsageMapper.insert(activeUserUsage);
                
                log.info("初始化今日使用统计记录成功，租户ID: {}", tenantId);
                return true;
            }
            
            log.debug("今日使用统计记录已存在，无需初始化，租户ID: {}", tenantId);
            return true;
        } catch (Exception e) {
            log.error("初始化今日使用统计记录失败: {}", e.getMessage(), e);
            throw new RuntimeException("初始化今日使用统计记录失败: " + e.getMessage());
        }
    }
    
    @Override
    public TenantUsage getTodayUsageOrCreate(Long tenantId) {
        try {
            LocalDate today = LocalDate.now();
            
            // 获取今天的使用统计
            TenantUsage usage = getTenantUsage(tenantId, today);
            
            // 如果不存在，则初始化
            if (usage == null) {
                initTodayUsage(tenantId);
                usage = getTenantUsage(tenantId, today);
            }
            
            log.debug("获取今日使用统计成功，租户ID: {}", tenantId);
            return usage;
        } catch (Exception e) {
            log.error("获取今日使用统计失败: {}", e.getMessage(), e);
            throw new RuntimeException("获取今日使用统计失败: " + e.getMessage());
        }
    }
    
    @Override
    @Transactional
    public boolean batchUpdateUsage(List<TenantUsage> usageList) {
        try {
            LocalDateTime now = LocalDateTime.now();
            
            for (TenantUsage usage : usageList) {
                usage.setUpdateTime(now);
                if (usage.getId() != null) {
                    tenantUsageMapper.updateById(usage);
                } else {
                    usage.setCreateTime(now);
                    tenantUsageMapper.insert(usage);
                }
            }
            
            log.info("批量更新租户使用统计成功，记录数: {}", usageList.size());
            return true;
        } catch (Exception e) {
            log.error("批量更新租户使用统计失败: {}", e.getMessage(), e);
            throw new RuntimeException("批量更新租户使用统计失败: " + e.getMessage());
        }
    }
    
    @Override
    public Map<String, Object> getSystemUsageReport(LocalDate statDate) {
        try {
            Map<String, Object> report = new HashMap<>();
            
            // 获取所有租户在指定日期的使用统计
            List<TenantUsage> usageList = tenantUsageMapper.selectByStatDate(statDate);
            
            // 按租户分组统计
            Map<Long, Map<String, Object>> tenantStats = new HashMap<>();
            for (TenantUsage usage : usageList) {
                Long tenantId = usage.getTenantId();
                tenantStats.computeIfAbsent(tenantId, k -> new HashMap<>());
                
                Map<String, Object> stats = tenantStats.get(tenantId);
                stats.put("tenantId", tenantId);
                stats.put(usage.getMetricName(), usage.getMetricValue());
            }
            
            report.put("date", statDate);
            report.put("tenantStats", tenantStats);
            report.put("totalTenants", tenantStats.size());
            
            log.debug("获取系统使用统计报告成功，日期: {}", statDate);
            return report;
        } catch (Exception e) {
            log.error("获取系统使用统计报告失败: {}", e.getMessage(), e);
            throw new RuntimeException("获取系统使用统计报告失败: " + e.getMessage());
        }
    }
    
    @Override
    @Transactional
    public int cleanupUsageData(LocalDate beforeDate) {
        try {
            LambdaQueryWrapper<TenantUsage> wrapper = new LambdaQueryWrapper<>();
            wrapper.lt(TenantUsage::getStatDate, beforeDate);
            
            int deletedCount = tenantUsageMapper.delete(wrapper);
            log.info("清理过期使用统计数据成功，清理日期: {} 之前的 {} 条记录", beforeDate, deletedCount);
            return deletedCount;
        } catch (Exception e) {
            log.error("清理过期使用统计数据失败: {}", e.getMessage(), e);
            throw new RuntimeException("清理过期使用统计数据失败: " + e.getMessage());
        }
    }
}